package app.framework.security.authentication;

import app.framework.constant.FrontConstants;
import app.framework.constant.FrameworkErrorConstants;
import app.framework.constant.FrameworkMsgConstants;
import app.framework.front.util.WebUtil;
import jasmine.framework.common.util.I18nUtil;
import jasmine.framework.common.util.JsonUtil;
import jasmine.framework.common.util.StringUtil;
import jasmine.framework.web.entity.WebResult;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * <p>
 * 未登录或会话超时时访问 JSON 接口，返回 JSON 结果。
 * </p>
 *
 * @author mh.z
 */
public class JsonApiSupportAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
    private static final String BACK_URL_PARAM_NAME = "backUrl";

    public JsonApiSupportAuthenticationEntryPoint(String loginFormUrl) {
        super(loginFormUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException {
        String url = WebUtil.getRequestUriWithoutContextPath(request);

        // 只对特定 URL 前缀的请求返回 JSON 格式的响应结果
        if (url.startsWith(FrontConstants.URL_PREFIX_API)) {
            // 设置响应体信息
            WebUtil.setResponseInfo(response, HttpServletResponse.SC_UNAUTHORIZED,
                    FrontConstants.RESPONSE_CONTENT_TYPE_JSON);

            String message = I18nUtil.getMessage(FrameworkMsgConstants.UNAUTHORIZED_OR_TIMEOUT);
            WebResult result = WebResult.error(FrameworkErrorConstants.UNAUTHORIZED_OR_TIMEOUT, message);
            String json = JsonUtil.toJson(result);
            // 写入数据到响应体
            WebUtil.writeAndFlush(response, json);
        } else {
            StringBuilder locationBuffer = new StringBuilder();
            locationBuffer.append(request.getContextPath());
            locationBuffer.append("/");

            String loginFormUrl = getLoginFormUrl();
            // 登录页面的路径
            if (loginFormUrl.startsWith("/")) {
                locationBuffer.append(loginFormUrl.substring(1));
            } else {
                locationBuffer.append(loginFormUrl);
            }

            String backUrl = getBackUrl(request);
            // 登录成功后跳转的路径
            if (StringUtil.isNotEmpty(backUrl)) {
                String encodedBackUrl = URLEncoder.encode(backUrl, StandardCharsets.UTF_8.toString());

                locationBuffer.append("?");
                locationBuffer.append(BACK_URL_PARAM_NAME);
                locationBuffer.append("=");
                locationBuffer.append(encodedBackUrl);
            }

            response.sendRedirect(locationBuffer.toString());
        }
    }

    /**
     * 返回登录成功后跳转的路径
     *
     * @param request
     * @return
     */
    protected String getBackUrl(HttpServletRequest request) {
        StringBuilder backUrlBuffer = new StringBuilder();
        backUrlBuffer.append(request.getRequestURI());

        String queryString = request.getQueryString();
        if (StringUtil.isNotEmpty(queryString)) {
            backUrlBuffer.append("?");
            backUrlBuffer.append(queryString);
        }

        return backUrlBuffer.toString();
    }

}
